Ext.apply(dbSchema, {    
    hasFK: function (table){
    	var hasFK = false;
    	Ext.iterate(table.columns, function(columnName, value) {
    		if (typeof value === 'string') {
                var parentTableName = columnName.charAt(0).toUpperCase() + columnName.substring(1);
                if(dbSchema.tables[parentTableName]) {
                	hasFK = true;
                	return false;
                }
            }
    	});
    	return hasFK;
    },
    isEntry: function(table) {
    	return table.columns.hasOwnProperty('name') && table.hasOwnProperty('label') && 
    		(!table.hasOwnProperty('entry') && !dbSchema.hasFK(table) || table.entry);
    }, 
    entryNames: function () {
        res = [];
        Ext.iterate(dbSchema.tables, function(tableName, table) {
        	dbSchema.isEntry(table) && res.push({id: tableName, name: table.label});
        });                
        return res;
    }
});

function rebuildTables(t) {
    console.log('Database rebuilding started');
    for (var tableName in dbSchema.tables) if (dbSchema.tables.hasOwnProperty(tableName)) {
        
        t.executeSql(
            'DROP TABLE IF EXISTS '+tableName+';',
            [], nullDataHandler, errorHandler
        );
        
        var columns = dbSchema.tables[tableName].columns,
            columnsDDL='', fkDDL='';
        
        for (var columnName in columns) if (columns.hasOwnProperty(columnName) && typeof columns[columnName]=='string') {
            columnsDDL += columnName + ' ' + columns[columnName] + ', ';
            parentTableName=columnName.charAt(0).toUpperCase()+columnName.substring(1);
            parentTable=dbSchema.tables[parentTableName];
            if (parentTable) fkDDL+=', foreign key ('+columnName+') references '+ parentTableName;
        };
        
        
        var ddl = 'CREATE TABLE IF NOT EXISTS '+tableName+' ( '+columnsDDL
            +' ts datetime default current_timestamp';
        
        var pkDDL = ddl.indexOf('primary') > 0;
        var table = dbSchema.tables[tableName];
        if (table.hasOwnProperty('Constraints')) {
            if (table.Constraints.hasOwnProperty('PK')) pkDDL='primary key '+table.Constraints.PK;
        }
        
        if (!pkDDL && columns.hasOwnProperty('id')) pkDDL='primary key (id)';
        
        if (pkDDL) ddl+=', '+pkDDL;
        
        ddl += fkDDL+' );';
        
        t.executeSql(ddl, [], nullDataHandler, errorHandler);
        
        console.log(ddl);

        for (var columnName in columns) if (columns.hasOwnProperty(columnName) && typeof columns[columnName]=='string') {
            parentTableName=columnName.charAt(0).toUpperCase()+columnName.substring(1);
            parentTable=dbSchema.tables[parentTableName];
            idxDDL = false;
            if (parentTable || columnName=='id') 
                idxDDL = 'create index '+tableName+'_'+columnName+' on '+ tableName + '('+columnName+')';
            
            if (idxDDL) {
                t.executeSql(idxDDL, [], nullDataHandler, errorHandler);
                console.log(idxDDL);
            }
            
        };

    }

}


function dbinit(name){
    var targetVersion = dbSchema.version;

    try {
        if (!window.openDatabase) {
            return false;
        } else {
            var shortName = name;
            var displayName = name + ' local data';
            var maxSize = 64*1024; // in bytes
            var db = openDatabase(shortName, "", displayName, maxSize);
            
            if (db.version < targetVersion)
                db.changeVersion (
                    db.version, targetVersion, rebuildTables,
                    function (err) {alert('error upgrading: '+err.message); return false;},
                    nullDataHandler
                )
            ;
            
            return db;
        }
        
    } catch(e) {
        if (e == 2) {
            alert("Invalid database version.");
        } else {
            alert("Unknown error at line "+e.line+', '+e+".");
        }
        return false;
    }
}


function nullDataHandler(transaction, results) {}
 
function errorHandler(transaction, error)
{
    console.log('Database error: '+error.message+' (Code '+error.code+')');
 
    return true;
}